package com.credithc.signature.manager.cron;

import com.credithc.signature.common.utils.DateUtil;
import com.credithc.signature.manager.vo.MethodVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.BoundZSetOperations;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ZSetOperations;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;

/**
 * @desc: <br/>
 * @author: Jingbo Hu<br/>
 * @time：2020年12⽉30⽇<br/>
 * @version：v1.0.0<br>
 */
@RestController
@RequestMapping("/manager/scs/v2")
@Slf4j
public class MethodCron {

    @Autowired
    private StringRedisTemplate redisTemplate;

    /**
     * 获取1分钟统计数据
     *
     * @return
     */
    @ResponseBody
    @PostMapping("/methodCron/oneminute")
    public Object getOneMinute() {
        String dateStr = DateUtil.getStandardDateStr();
        BoundZSetOperations<String, String> zSetOps = redisTemplate.boundZSetOps(dateStr + "#method#oneminute");
        Long aLong = zSetOps.zCard();
        Set<ZSetOperations.TypedTuple<String>> typedTuples = zSetOps.reverseRangeWithScores(0, aLong);
        return getMethodVos(typedTuples);
    }

    /**
     * 获取15分钟统计数据
     *
     * @return
     */
    @ResponseBody
    @PostMapping("/methodCron/fifteeenminute")
    public Object getFifteenMinute() {
        String dateStr = DateUtil.getStandardDateStr();
        BoundZSetOperations<String, String> zSetOps = redisTemplate.boundZSetOps(dateStr + "#method#fifteenminute");
        Long aLong = zSetOps.zCard();
        Set<ZSetOperations.TypedTuple<String>> typedTuples = zSetOps.reverseRangeWithScores(0, aLong);
        return getMethodVos(typedTuples);
    }

    /**
     * 获取60分钟统计数据
     *
     * @return
     */
    @ResponseBody
    @PostMapping("/methodCron/onehour")
    public Object getOneHour() {
        String dateStr = DateUtil.getStandardDateStr();
        BoundZSetOperations<String, String> zSetOps = redisTemplate.boundZSetOps(dateStr + "#method#onehour");
        Long aLong = zSetOps.zCard();
        Set<ZSetOperations.TypedTuple<String>> typedTuples = zSetOps.reverseRangeWithScores(0, aLong);
        return getMethodVos(typedTuples);
    }

    /**
     * 获取一天统计数据
     *
     * @return
     */
    @ResponseBody
    @PostMapping("/methodCron/oneday")
    public Object getOneDay() {
        String dateStr = DateUtil.getStandardDateStr();
        BoundZSetOperations<String, String> zSetOps = redisTemplate.boundZSetOps(dateStr + "#method#oneday");
        Long aLong = zSetOps.zCard();
        Set<ZSetOperations.TypedTuple<String>> typedTuples = zSetOps.reverseRangeWithScores(0, aLong);
        return getMethodVos(typedTuples);
    }

    /**
     * 封装返回参数
     *
     * @param typedTuples
     * @return
     */
    private List<MethodVo> getMethodVos(Set<ZSetOperations.TypedTuple<String>> typedTuples) {
        List<MethodVo> list = new ArrayList<>();
        int temp = 1;
        for (ZSetOperations.TypedTuple<String> typedTuple : typedTuples) {
            String value = typedTuple.getValue();
            Double score = typedTuple.getScore();
            if ("executeCount".equals(value)) {
                temp = new Double(score).intValue();
            }
        }
        for (ZSetOperations.TypedTuple<String> typedTuple : typedTuples) {
            MethodVo methodVo = new MethodVo();
            String value = typedTuple.getValue();
            Double score = typedTuple.getScore();
            if ("executeCount".equals(value)) {
                continue;
            }
            if ("handle".equals(value)) {
                continue;
            }

            BigDecimal num1 = BigDecimal.valueOf(score);
            BigDecimal num2 = BigDecimal.valueOf(temp);
            BigDecimal divide = num1.divide(num2, 3, BigDecimal.ROUND_UP);
            methodVo.setName(value);
            methodVo.setValue(divide.doubleValue());
            list.add(methodVo);
        }
        return list;
    }

    // =================================定时任务删除数据=================================

    /**
     * 每1分钟
     */
    @Scheduled(cron = "0 */1 * * * ?")
    public void removeOneminuteData() {
        log.info("执行定时任务[删除每1分钟方法耗时统计数据]每1分钟执行,现在时间为：" + DateUtil.getDefaultDateTimeStr());
        try {
            String dateStr = DateUtil.getStandardDateStr();
            BoundZSetOperations<String, String> zSetOps = redisTemplate.boundZSetOps(dateStr + "#method#oneminute");
            Long aLong = zSetOps.zCard();
            zSetOps.removeRange(0, aLong);
        } catch (Exception e) {
            log.error("执行定时任务[删除每1分钟方法耗时统计数据]失败...", e);
        }
    }

    /**
     * 每15分钟
     */
    @Scheduled(cron = "0 */15 * * * ?")
    public void removeFifteenminuteData() {
        log.info("执行定时任务[删除每15分钟方法耗时统计数据]每15分钟执行,现在时间为：" + DateUtil.getDefaultDateTimeStr());
        try {
            String dateStr = DateUtil.getStandardDateStr();
            BoundZSetOperations<String, String> zSetOps = redisTemplate.boundZSetOps(dateStr + "#method#fifteenminute");
            Long aLong = zSetOps.zCard();
            zSetOps.removeRange(0, aLong);
        } catch (Exception e) {
            log.error("执行定时任务[删除每15分钟方法耗时统计数据]失败...", e);
        }
    }

    /**
     * 每1小时执行
     */
    @Scheduled(cron = "0 0 */1 * * ?")
    public void removeOnehourData() {
        log.info("执行定时任务[删除每小时方法耗时统计数据]每小时执行,现在时间为：" + DateUtil.getDefaultDateTimeStr());
        try {
            String dateStr = DateUtil.getStandardDateStr();
            BoundZSetOperations<String, String> zSetOps = redisTemplate.boundZSetOps(dateStr + "#method#onehour");
            Long aLong = zSetOps.zCard();
            zSetOps.removeRange(0, aLong);
        } catch (Exception e) {
            log.error("执行定时任务[删除每小时方法耗时统计数据]失败...", e);
        }
    }

    /**
     * 每天凌晨0点执行一次
     */
    @Scheduled(cron = "0 0 0 */1 * ?")
    public void removeOnedayData() {
        log.info("执行定时任务[删除每方法耗时统计数据]每天0点执行一次,现在时间为：" + DateUtil.getDefaultDateTimeStr());
        try {
            String dateStr = DateUtil.getYesterdayStander();
            BoundZSetOperations<String, String> zSetOps = redisTemplate.boundZSetOps(dateStr + "#method#oneday");
            Long aLong = zSetOps.zCard();
            zSetOps.removeRange(0, aLong);
        } catch (Exception e) {
            log.error("执行定时任务[删除每天方法耗时统计数据]失败...", e);
        }
    }

}
